#pragma once
#include <queue>
#include <mutex>
#include <string>
#include <system_error>
#include <stdexcept>
#include <memory>
#include "global.h"
#include <cstring>
#include <netinet/in.h>
#include <atomic>
#include <chrono>
class HeadBuf{
public:
    explicit HeadBuf(size_t head_len);
    void clear() {
        std::memset(_buf.get(), 0, _head_len);
        _offset = 0;
    }
    ~HeadBuf();
    std::unique_ptr<char[]> _buf;
    size_t _head_len;
    size_t _offset;
};

//数据buffer
class DataBuf{
public:
    //仅分配长度
    DataBuf(uint16_t msg_type, size_t body_len);
    //头部＋体
    DataBuf(uint16_t msg_type, const std::string& body);
    ~DataBuf(); 
    uint16_t _msg_type;//数据类型id, 比如1001表示登录，1002表示聊天等。
    std::unique_ptr<char[]> _buf;
    size_t _total_len;
    size_t _offset;
};
class IOThread;
//todo....单例
class Session : public std::enable_shared_from_this<Session>{
public:
    friend class IOThread;
    Session(int fd, std::shared_ptr<IOThread>io_thread);
    ~Session();

    Session(const Session&) = delete;
    Session& operator=(const Session&) = delete;

    void Send(const std::string& data, size_t msg_type);//对外发送接口（投递给io线程）
    IOStatus RecvData();// 接收数据（由IO线程调用）
    IOStatus SendData(std::shared_ptr<DataBuf> data);// 发送数据（由IO线程调用）
    int GetFd() const { return _fd; }// 获取Socket FD

    void update_active_time();//更新最后活动时间
    std::chrono::steady_clock::time_point get_last_active_time() const {// 获取最后活动时间
        return _last_active_time;
    }
private:
    // void enqueue_data(std::shared_ptr<DataBuf> data);
    // int send_data(std::shared_ptr<DataBuf> data);
    bool ParseHead();
private:
    int _fd; // 客户端Socket FD
    std::shared_ptr<IOThread> _io_thread; // 所属IO线程
    RecvStage _recv_stage;                // 接收状态
    SendStage _send_stage;                // 发送状态
    std::unique_ptr<HeadBuf> _head_buf;   // 头部缓存
    std::unique_ptr<DataBuf> _body_buf;   // 体缓存（接收用）
    std::queue<std::shared_ptr<DataBuf>> _send_queue; // 发送队列 (发送队列仍由 shared_ptr 管理)
    std::mutex _send_mtx;                 // 发送队列互斥锁
    std::mutex _session_mtx;
    // IOThread 会写入此变量，定时检查任务会读取此变量
    std::atomic<std::chrono::steady_clock::time_point> _last_active_time; 
};
